/*
 *  Copyright 2019-2020 Zheng Jie
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package me.zhengjie.modules.mnt.service.impl

import cn.hutool.core.util.IdUtil
import jakarta.persistence.criteria.CriteriaBuilder
import jakarta.persistence.criteria.CriteriaQuery
import jakarta.persistence.criteria.Root

import me.zhengjie.common.utils.PageResult
import me.zhengjie.common.utils.PageUtil
import me.zhengjie.common.utils.QueryHelp
import me.zhengjie.common.utils.ValidationUtil
import me.zhengjie.logging.slf4j.logError
import me.zhengjie.modules.mnt.domain.Database
import me.zhengjie.modules.mnt.repository.DatabaseRepository
import me.zhengjie.modules.mnt.service.DatabaseService
import me.zhengjie.modules.mnt.service.dto.DatabaseDto
import me.zhengjie.modules.mnt.service.dto.DatabaseQueryCriteria
import me.zhengjie.modules.mnt.service.mapstruct.DatabaseMapper
import me.zhengjie.modules.mnt.util.SqlUtils
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.domain.Specification
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.io.IOException
import java.util.function.Supplier
import jakarta.servlet.http.HttpServletResponse
import me.zhengjie.common.utils.FileUtil

/**
 * @author zhanghouying
 * @date 2019-08-24
 */
@Service
class DatabaseServiceImpl (
    private val databaseRepository: DatabaseRepository? = null,
    private val databaseMapper: DatabaseMapper? = null
): DatabaseService {
    override fun queryAll(criteria: DatabaseQueryCriteria?, pageable: Pageable?): PageResult<DatabaseDto?> {
        val page: Page<Database> = databaseRepository!!.findAll(
            Specification { root: Root<Database?>?, criteriaQuery: CriteriaQuery<*>?, criteriaBuilder: CriteriaBuilder? ->
                QueryHelp.getPredicate(
                    root!!,
                    criteria,
                    criteriaBuilder!!
                )
            }, pageable!!) as Page<Database>
        return PageUtil.toPage(page.map{ database:Database? ->databaseMapper!!.toDto(database)}) as PageResult<DatabaseDto?>
    }

    override fun queryAll(criteria: DatabaseQueryCriteria?): List<DatabaseDto?> {
        return databaseMapper!!.toDto(databaseRepository!!.findAll(Specification { root: Root<Database?>?, criteriaQuery: CriteriaQuery<*>?, criteriaBuilder: CriteriaBuilder? ->
            QueryHelp.getPredicate(
                root!!,
                criteria,
                criteriaBuilder!!
            )
        }))!!
    }

    override fun findById(id: String?): DatabaseDto {
        val database: Database = databaseRepository!!.findById(id!!).orElseGet(Supplier { Database() })!!
        ValidationUtil.isNull(database.id, "Database", "id", id)
        return databaseMapper!!.toDto(database)!!
    }

    @Transactional(rollbackFor = [Exception::class])
    override fun create(resources: Database) {
        resources.id=(IdUtil.simpleUUID())
        databaseRepository!!.save<Database>(resources)
    }

    @Transactional(rollbackFor = [Exception::class])
    override fun update(resources: Database) {
        val database: Database = databaseRepository!!.findById(resources.id!!).orElseGet(
            Supplier { Database() })!!
        ValidationUtil.isNull(database.id, "Database", "id", resources.id!!)
        database.copy(resources)
        databaseRepository.save<Database>(database)
    }

    @Transactional(rollbackFor = [Exception::class])
    override fun delete(ids: Set<String?>) {
        for (id in ids) {
            databaseRepository!!.deleteById(id!!)
        }
    }

    override fun testConnection(resources: Database): Boolean {
        return try {
            SqlUtils.testConnection(resources.jdbcUrl!!, resources.userName!!, resources.pwd!!)
        } catch (e: Exception) {
            logError(e.message!!)
            false
        }
    }

    @Throws(IOException::class)
    override fun download(queryAll: List<DatabaseDto?>, response: HttpServletResponse?) {
        val list: MutableList<Map<String?, Any?>> = ArrayList()
        for (databaseDto in queryAll) {
            val map: MutableMap<String?, Any?> = LinkedHashMap()
            map["数据库名称"] = databaseDto!!.name!!
            map["数据库连接地址"] = databaseDto.jdbcUrl!!
            map["用户名"] = databaseDto.userName!!
            map["创建日期"] = databaseDto.createTime!!
            list.add(map)
        }
        FileUtil.downloadExcel(list, response!!)
    }
}